import json
import random
from PIL import Image
import cv2

import requests
import execjs
import os
_dir = os.path.dirname(os.path.abspath(__file__))


class TX:
    def __init__(self):
        self.headers = {
            "Accept": "application/json, text/javascript, */*; q=0.01",
            "Accept-Language": "zh-CN,zh;q=0.9",
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
            "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
            "Origin": "https://turing.captcha.gtimg.com",
            "Pragma": "no-cache",
            "Referer": "https://turing.captcha.gtimg.com/",
            "Sec-Fetch-Dest": "empty",
            "Sec-Fetch-Mode": "cors",
            "Sec-Fetch-Site": "cross-site",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
        }
        self.sess = ''
        self.md5 = ''
        self.prefix = ''
        self.tdc_url = ''
        self.image_url = ''
        self.host = 'https://turing.captcha.qcloud.com'
        self.slice_path = os.path.join(_dir, "slice.png")
        self.background_path = os.path.join(_dir, "background.png")

    @classmethod
    def __ease_out_expo(cls, sep):
        if sep == 1:
            return 1
        else:
            return 1 - pow(2, -10 * sep)

    def get_slide_track(self, distance_x, distance_y):
        """
        根据滑动距离生成滑动轨迹
        :param distance_x: 需要滑动的距离
        :param distance_y: 纵坐标距离
        :return: 滑动轨迹<type 'list'>: [[x,y,t], ...]
            x: 已滑动的横向距离
            y: 已滑动的纵向距离, 除起点外, 均为0
            t: 滑动过程消耗的时间, 单位: 毫秒
        """

        if not isinstance(distance_x, int) or distance_x < 0:
            raise ValueError(f"distance类型必须是大于等于0的整数: distance: {distance_x}, type: {type(distance_x)}")

        # 记录上一次滑动的距离
        _x = random.randint(20, 50)
        _y = random.randint(distance_y - 3, distance_y + 3)
        # 初始化轨迹列表
        slide_track = [[_x, _y]]
        # 共记录count次滑块位置信息
        count = 30 + int(distance_x / 2)
        for i in range(count):
            # 已滑动的横向距离
            x = round(self.__ease_out_expo(i / count) * distance_x)
            # 滑动过程消耗的时间
            if x <= _x:
                continue
            _y += random.choices([-1 , 0, 1], weights=[1, 8, 1], k=1)[0]
            slide_track.append([x, _y])
            _x = x
        slide_track.append([distance_x, distance_y])
        return slide_track
    def get_prehandle(self):
        url = self.host + "/cap_union_prehandle"
        params = {
            "aid": "199999861",
            "protocol": "https",
            "accver": "1",
            "showtype": "popup",
            "ua": "TW96aWxsYS81LjAgKFdpbmRvd3MgTlQgMTAuMDsgV2luNjQ7IHg2NCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzExMi4wLjAuMCBTYWZhcmkvNTM3LjM2",
            "noheader": "1",
            "fb": "1",
            "aged": "0",
            "enableAged": "0",
            "enableDarkMode": "0",
            "grayscale": "1",
            "clientype": "2",
            "cap_cd": "",
            "uid": "",
            "lang": "zh-cn",
            "entry_url": "https://cloud.tencent.com/product/captcha",
            "elder_captcha": "0",
            "js": "/tcaptcha-frame.c055d939.js",
            "login_appid": "",
            "wb": "2",
            "subsid": "1",
            "callback": "_aq_464019",
            "sess": ""
        }
        response = requests.get(url, headers=self.headers, params=params)
        data = json.loads(response.text[len(params['callback']) + 1 : len(response.text) - 1])
        
        self.sess = data['sess']
        self.tdc_url = self.host + data['data']['comm_captcha_cfg']['tdc_path']
        self.md5 = data['data']['comm_captcha_cfg']['pow_cfg']['md5']
        self.prefix = data['data']['comm_captcha_cfg']['pow_cfg']['prefix']
        self.image_url = self.host + data['data']['dyn_show_info']['sprite_url']
    
        print(response)

    def get_image(self):

        # 获取滑块图片
        response = requests.get(self.image_url, headers=self.headers)
        with open(self.slice_path, "wb") as f:
            f.write(response.content)

        # 获取背景图片
        response = requests.get(self.image_url.replace("index=0", "index=1"), headers=self.headers)
        with open(self.background_path, "wb") as f:
            f.write(response.content)

        # 图片裁剪
        with Image.open(self.slice_path) as img:
            cropped = img.crop([140,495,260,600])
            rgb_img = cropped.convert("RGB")
            rgb_img.save(self.slice_path)
        
    def find_slider_offset(self):

        bg = cv2.imread(self.background_path, 0) #背景图
        tp = cv2.imread(self.slice_path, 0) #缺口图

        # 模板匹配
        result = cv2.matchTemplate(bg, tp, cv2.TM_CCOEFF_NORMED)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
        # 移到中心位置
        x = max_loc[0] + 50
        y = max_loc[1] + 53
        # 坐标缩放
        x = int(x / 2.2)
        y = int(y / 2.5)
        return x , y



    def verify(self, position):
        # 获取配对js
        response = requests.get(self.tdc_url, headers=self.headers)
        tdc_code = response.text

        url = self.host + "/cap_union_new_verify"

        with open(os.path.join(_dir, "main.js"), encoding='utf-8') as f:
            js_code = f.read().replace("code = ''", tdc_code)
        js = execjs.compile(js_code)

        point_array = position.split('|')
        track = self.get_slide_track(int(point_array[0]), int(point_array[1]))
        # track = [[4,264],[4,264],[4,264],[14,264],[14,264],[14,264],[24,263],[24,263],[24,263],[30,262],[30,262],[30,262],[36,260],[36,260],[36,260],[40,257],[40,257],[40,257],[42,255],[42,255],[42,255],[44,253],[44,253],[44,253],[45,251],[45,251],[45,251],[45,251],[45,251],[45,251],[44,250],[44,250],[44,250],[41,250],[41,250],[41,250],[36,250],[36,250],[36,250],[35,250],[35,250],[35,250],[34,250],[34,250],[34,250],[33,249],[33,249],[33,249],[34,247],[34,247],[34,247],[35,247],[35,247],[35,247],[36,246],[36,246],[36,246],[38,245],[38,245],[38,245],[40,240],[40,240],[40,240],[42,237],[42,237],[42,237],[42,236],[42,236],[42,236],[44,234],[44,234],[44,234],[45,233],[45,233],[45,233],[48,233],[48,233],[48,233],[50,233],[50,233],[50,233],[51,233],[51,233],[51,233],[53,233],[53,233],[53,233],[54,233],[54,233],[54,233],[56,233],[56,233],[56,233],[58,233],[58,233],[58,233],[60,233],[60,233],[60,233],[62,233],[62,233],[62,233],[62,233],[62,233],[62,233],[63,233],[63,233],[63,233],[64,233],[64,233],[64,233],[65,233],[65,233],[65,233],[67,233],[67,233],[67,233],[68,233],[68,233],[68,233],[69,233],[69,233],[69,233],[69,234],[69,234],[69,234],[70,235],[70,235],[70,235],[70,235],[70,235],[70,235],[70,236],[70,236],[70,236],[71,237],[71,237],[71,237],[71,238],[71,238],[71,238],[71,239],[71,239],[71,239],[71,240],[71,240],[71,240],[71,241],[71,241],[71,241],[71,242],[71,242],[71,242],[71,243],[71,243],[71,243],[71,244],[71,244],[71,244],[71,246],[71,246],[71,246],[71,247],[71,247],[71,247],[71,249],[71,249],[71,249],[71,249],[71,249],[71,249],[71,250],[71,250],[71,250],[71,251],[71,251],[71,251],[71,253],[71,253],[71,253],[71,253],[71,253],[71,253],[71,254],[71,254],[71,254],[72,256],[72,256],[72,256],[72,257],[72,257],[72,257],[72,257],[72,257],[72,257],[72,258],[72,258],[72,258],[72,259],[72,259],[72,259],[72,261],[72,261],[72,261],[72,263],[72,263],[72,263],[72,265],[72,265],[72,265],[72,267],[72,267],[72,267],[71,268],[71,268],[71,268],[70,269],[70,269],[70,269],[70,271],[70,271],[70,271],[70,273],[70,273],[70,273],[69,273],[69,273],[69,273],[68,274],[68,274],[68,274],[68,275],[68,275],[68,275],[68,276],[68,276],[68,276],[68,277],[68,277],[68,277],[68,278],[68,278],[68,278],[68,279],[68,279],[68,279],[68,280],[68,280],[68,280],[68,281],[68,281],[68,281],[68,282],[68,282],[68,282],[68,283],[68,283],[68,283],[68,284],[68,284],[68,284],[68,284],[68,284],[68,284],[70,284],[70,284],[70,284],[71,284],[71,284],[71,284],[72,284],[72,284],[72,284],[72,284],[72,284],[72,284],[74,284],[74,284],[74,284],[74,284],[74,284],[74,284],[76,284],[76,284],[76,284],[76,284],[76,284],[76,284],[77,284],[77,284],[77,284],[78,284],[78,284],[78,284],[78,284],[78,284],[78,284],[79,284],[79,284],[79,284],[80,284],[80,284],[80,284],[80,284],[80,284],[80,284],[82,284],[82,284],[82,284],[83,284],[83,284],[83,284],[84,284],[84,284],[84,284],[84,284],[84,284],[84,284],[86,284],[86,284],[86,284],[86,284],[86,284],[86,284],[87,284],[87,284],[87,284],[88,284],[88,284],[88,284],[88,284],[88,284],[88,284],[89,284],[89,284],[89,284],[90,284],[90,284],[90,284],[91,284],[91,284],[91,284],[93,284],[93,284],[93,284],[94,284],[94,284],[94,284],[96,284],[96,284],[96,284],[97,284],[97,284],[97,284],[99,284],[99,284],[99,284],[101,284],[101,284],[101,284],[102,284],[102,284],[102,284],[104,284],[104,284],[104,284],[105,284],[105,284],[105,284],[107,284],[107,284],[107,284],[108,284],[108,284],[108,284],[108,284],[108,284],[108,284],[109,284],[109,284],[109,284],[110,284],[110,284],[110,284],[110,284],[110,284],[110,284],[112,284],[112,284],[112,284],[112,284],[112,284],[112,284],[114,284],[114,284],[114,284],[116,284],[116,284],[116,284],[118,284],[118,284],[118,284],[120,284],[120,284],[120,284],[124,284],[124,284],[124,284],[128,284],[128,284],[128,284],[133,284],[133,284],[133,284],[137,284],[137,284],[137,284],[142,284],[142,284],[142,284],[148,284],[148,284],[148,284],[154,284],[154,284],[154,284],[158,284],[158,284],[158,284],[163,284],[163,284],[163,284],[168,284],[168,284],[168,284],[174,284],[174,284],[174,284],[179,284],[179,284],[179,284],[184,284],[184,284],[184,284],[189,284],[189,284],[189,284],[193,284],[193,284],[193,284],[198,284],[198,284],[198,284],[202,284],[202,284],[202,284],[205,284],[205,284],[205,284],[208,284],[208,284],[208,284],[211,284],[211,284],[211,284],[214,284],[214,284],[214,284],[216,284],[216,284],[216,284],[218,284],[218,284],[218,284],[220,284],[220,284],[220,284],[222,284],[222,284],[222,284],[224,284],[224,284],[224,284],[224,284],[224,284],[224,284],[226,284],[226,284],[226,284],[226,284],[226,284],[226,284],[227,284],[227,284],[227,284],[228,284],[228,284],[228,284],[230,284],[230,284],[230,284],[230,284],[230,284],[230,284],[231,284],[231,284],[231,284],[232,284],[232,284],[232,284],[234,284],[234,284],[234,284],[236,284],[236,284],[236,284],[237,284],[237,284],[237,284],[240,283],[240,283],[240,283],[240,283],[240,283],[240,283],[243,283],[243,283],[243,283],[246,282],[246,282],[246,282],[247,282],[247,282],[247,282],[249,282],[249,282],[249,282],[250,282],[250,282],[250,282],[253,282],[253,282],[253,282],[255,282],[255,282],[255,282],[256,282],[256,282],[256,282],[258,282],[258,282],[258,282],[258,282],[258,282],[258,282],[260,282],[260,282],[260,282],[261,281],[261,281],[261,281],[262,281],[262,281],[262,281],[262,281],[262,281],[262,281],[263,281],[263,281],[263,281],[264,281],[264,281],[264,281],[264,280],[264,280],[264,280],[265,280],[265,280],[265,280],[266,280],[266,280],[266,280],[266,279],[266,279],[266,279],[268,279],[268,279],[268,279],[269,278],[269,278],[269,278],[270,278],[270,278],[270,278],[270,278],[270,278],[270,278]]
        print("滑块轨迹", track)
        collect = js.call("get_collect", track)
        print("collect:", collect, len(collect))
        eks = js.call("get_info")
        print("eks:", eks)
        pos = js.call("get_pos", int(point_array[0]), int(point_array[1]))
        print("坐标转换：", pos)

        pow_answer = js.call("get_pow_answer", self.prefix, self.md5)
        print("坐标转换：", pow_answer)

        # collect = "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"

        data = {
            "collect": collect,
            "tlg": len(collect),
            "eks": eks,
            "sess": self.sess,
            "ans": json.dumps([{"elem_id": 1, "type": "DynAnswerType_POS", "data": pos}], separators=(",", ":")),
            "pow_answer": self.prefix + str(pow_answer['ans']),
            "pow_calc_time": pow_answer['duration']
        }
        response = requests.post(url, headers=self.headers, data=data)

        print(response.text)
        print(response)


if __name__ == '__main__':
    t = TX()
    t.get_prehandle()
    t.get_image()
    x, y = t.find_slider_offset()
    print(x, y)
    t.verify(str(x) + "|" + str(y))
